package com.medvalley.tcm.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.medvalley.tcm.base.BusinessException;
import com.medvalley.tcm.base.Constants;
import com.medvalley.tcm.base.Result;
import com.medvalley.tcm.cache.RedisCache;
import com.medvalley.tcm.dao.UserInfoDao;
import com.medvalley.tcm.dao.UserInfoDetailDao;
import com.medvalley.tcm.dao.UserLevelConfigDao;
import com.medvalley.tcm.domain.UserInfo;
import com.medvalley.tcm.domain.UserInfoDetail;
import com.medvalley.tcm.domain.UserLevelConfig;
import com.medvalley.tcm.service.UserInfoService;
import com.medvalley.tcm.utils.EncryptUtils;
import com.medvalley.tcm.vo.outputvo.UserConfigOutputVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoDao userInfoDao;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private UserInfoDetailDao userInfoDetailDao;

    @Autowired
    private UserLevelConfigDao userLevelConfigDao;

    @Override
    public Result register(String phone, String password) {
        Map<String, Object> resultMap = Maps.newHashMap();
        Result result = new Result();
        UserInfo oldUser = userInfoDao.findOneByPhone(phone);
        if (oldUser != null) {
            resultMap.put("status", 0);
            resultMap.put("message", "该手机号已经注册");
            result.setCode(Constants.HTTP_ERROR_CODE);
            result.setData(resultMap);
            return result;
        }
        UserInfo userInfo = new UserInfo();
        Date now = new Date();
        userInfo.setPhone(phone);
        userInfo.setPassword(EncryptUtils.sha256(password));
        userInfo.setCreateTime(now);
        userInfo.setUpdateTime(now);
        userInfoDao.save(userInfo);
        resultMap.put("userInfo", userInfo);
        String token = this.generateToken(phone);
        resultMap.put("token", token);

        result.setCode(Constants.HTTP_SUCCESS_CODE);
        result.setData(resultMap);
        return result;
    }

    @Override
    public Result loginBySmsCode(String phone) {
        Map<String, Object> resultMap = new HashMap<>();
        Result result = new Result();
        UserInfo userInfo = userInfoDao.findOneByPhone(phone);
        if (userInfo == null) {
            resultMap.put("status", 1);
            resultMap.put("message", "该手机号没有注册");
            result.setCode(Constants.HTTP_ERROR_CODE);
            result.setData(resultMap);
            return result;
        }
        resultMap = this.doLogin(userInfo);
        result.setCode(Constants.HTTP_SUCCESS_CODE);
        result.setData(resultMap);
        return result;
    }

    @Override
    public Result loginByPassword(String phone, String password) {
        Map<String, Object> resultMap = new HashMap<>();
        Result result = new Result();
        UserInfo userInfo = userInfoDao.findOneByPhone(phone);
        if (userInfo == null) {
            resultMap.put("status", 1);
            resultMap.put("message", "该手机号没有注册");
            result.setCode(Constants.HTTP_ERROR_CODE);
            result.setData(resultMap);
            return result;
        }
        String encryptPassword = EncryptUtils.sha256(password);
        if (!encryptPassword.equals(userInfo.getPassword())) {
            resultMap.put("status", 2);
            resultMap.put("message", "密码错误");
            result.setCode(Constants.HTTP_ERROR_CODE);
            result.setData(resultMap);
            return result;
        }
        resultMap = this.doLogin(userInfo);
        result.setCode(Constants.HTTP_SUCCESS_CODE);
        result.setData(resultMap);
        return result;
    }

    private Map<String, Object> doLogin(UserInfo userInfo) {
        Map<String, Object> resultMap = new HashMap<>();
        String token = this.generateToken(userInfo.getPhone());
        resultMap.put("token", token);
        resultMap.put("userInfo", userInfo);
        return resultMap;
    }

    private String generateToken(String phone) {
        String token = DigestUtils.md5DigestAsHex(phone.getBytes());
        redisCache.setValue(Constants.SESSION_PREFIX + token, phone);
        return token;
    }

    @Override
    public UserInfo getUserInfoByPhone(String phone) {
        return userInfoDao.findOneByPhone(phone);
    }

    @Override
    public UserInfoDetail updateUserInfoDetail(String sessionPhone, UserInfoDetail userInfoDetail) {
        UserInfo userInfo = this.getUserInfoByPhone(sessionPhone);
        userInfoDetail.setUserId(userInfo.getId());
        userInfo.setRealName(userInfoDetail.getRealName());
        String detailGender = userInfoDetail.getGender();
        if (detailGender == null) {
            userInfo.setGender(0);
        } else if ("男".equals(detailGender)) {
            userInfo.setGender(1);
        } else if ("女".equals(detailGender)) {
            userInfo.setGender(2);
        }
        Date now = new Date();
        UserInfoDetail oldDetail = userInfoDetailDao.findOneByUserId(userInfoDetail.getUserId());
        if (oldDetail != null) {
            userInfoDetail.setId(oldDetail.getId());
            userInfoDetail.setHeadIcon(oldDetail.getHeadIcon());
        } else {
            userInfoDetail.setCreateTime(now);
        }
        userInfoDetail.setUpdateTime(now);
        userInfoDetailDao.save(userInfoDetail);
        return userInfoDetail;
    }

    @Override
    public UserInfoDetail getUserInfoDetail(String phone) {
        UserInfo userInfo = userInfoDao.findOneByPhone(phone);
        long userId = userInfo.getId();
        UserInfoDetail userInfoDetail = userInfoDetailDao.findOneByUserId(userId);
        if (userInfoDetail == null) {
            userInfoDetail = new UserInfoDetail();
            userInfoDetail.setUserId(userId);
        }
        return userInfoDetail;
    }

    @Override
    @Transactional
    public int modifyUserPhone(String oldPhone, String newPhone, String token) {
        UserInfo userInfo = userInfoDao.findOneByPhone(oldPhone);
        userInfo.setPhone(newPhone);
        userInfoDao.save(userInfo);
        redisCache.setValue(Constants.SESSION_PREFIX + token, newPhone);
        return 1;
    }

    @Override
    public void resetPassword(String phone, String password) {
        UserInfo userInfo = userInfoDao.findOneByPhone(phone);
        if (userInfo == null) {
            throw new BusinessException("该手机号没有注册");
        }
        userInfo.setPassword(EncryptUtils.sha256(password));
        userInfoDao.save(userInfo);
    }

    @Override
    public void logout(String token) {
        redisCache.deleteCache(Constants.SESSION_PREFIX + token);
    }

    @Override
    public void setHeadIcon(String url, String phone) {
        UserInfo userInfo = userInfoDao.findOneByPhone(phone);
        UserInfoDetail userInfoDetail = userInfoDetailDao.findOneByUserId(userInfo.getId());
        Date now = new Date();
        if (userInfoDetail == null) {
            userInfoDetail = new UserInfoDetail();
            userInfoDetail.setUserId(userInfo.getId());
            userInfoDetail.setCreateTime(now);
        }
        userInfoDetail.setUpdateTime(now);
        userInfoDetail.setHeadIcon(url);
        userInfoDetailDao.save(userInfoDetail);
    }

    @Override
    public List<UserConfigOutputVo> getUserLevel(String phone) {
        List<UserConfigOutputVo> userConfigOutputVoList = Lists.newArrayList();
        UserInfo userInfo = userInfoDao.findOneByPhone(phone);
        if (userInfo == null) {
            return userConfigOutputVoList;
        }
        int configValue = userInfo.getUserLevelValue();
        UserLevelConfig config = userLevelConfigDao.findOneByLevelValue(configValue);
        List<UserLevelConfig.ConfigValue> configValueList = config.parseConfigValue();
        configValueList.forEach(e -> {
            UserConfigOutputVo outputVo = new UserConfigOutputVo();
            BeanUtils.copyProperties(e, outputVo);
            userConfigOutputVoList.add(outputVo);
        });
        return userConfigOutputVoList;
    }

}
